import pandas as pd
import numpy as np
import re
import missingno as msno
import os
import glob
import platform
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline
import warnings
warnings.filterwarnings('ignore')
path = "c:/Windows/Fonts/malgun.ttf"
from matplotlib import font_manager, rc
if platform.system() == 'Darwin':
rc('font', family='AppleGothic')
elif platform.system() == 'Windows':
font_name = font_manager.FontProperties(fname=path).get_name()
rc('font', family=font_name)
else:
print('Unknown system... sorry~~~~')
plt.rcParams['axes.unicode_minus'] = False
from IPython.display import set_matplotlib_formats
set_matplotlib_formats('retina')
pwd
'c:\\Users\\pc\\Desktop\\데이터스토리'
folder_path = "./data/소상공인매출및사업자정보/"
all_files = glob.glob(folder_path + "/*.csv")
df_seller = pd.DataFrame() # 데이터 넣을 데이터프레임 선언 (데이터마다 변수명 다르게)
li = []
for filename in all_files:
df = pd.read_csv(filename, index_col=None, header=0)
li.append(df)
df_seller = pd.concat(li, axis=0, ignore_index=True) # 데이터프레임에 데이터 할당 (변수명 일치하도록 주의)
df_seller.head() # 사업자등록번호, 업종코드, 기업번호 등은 현 단계 분석에 적합하지 않음
기준년월 | 성별코드 | 연령대코드 | 사업자등록번호 | 시도명 | 신청년월 | 개업일자 | 과세유형명 | 이전과세년도 | 사업소득과세금액 | 근로소득과세금액 | 부가가치과세금액 | 신청금액 | 자금종류대분류명 | 자금종류중분류명 | 업종대분류명 | 업종중분류명 | 업종소분류명 | 업종코드 | 기업번호 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 2020-10 | M | 50 | 11802***** | 경기도 | 2020-08 | 1996-05-01 | 일반과세자 | 2019 | 0 | 0 | 8058670 | 50000000 | 경기도자금 | 소상공인지원자금 | C제조업(10~34) | 특수목적용기계제조업 | 주형및금형제조업 | C29294 | Q8OLE6NDWIB5JYLXkZcELA== |
1 | 2020-10 | F | 30 | 13547***** | 경기도 | 2020-08 | 2017-10-30 | 일반과세자 | 2019 | 0 | 0 | 8491460 | 30000000 | 일반자금 | 소상공인지원자금 | G도매및소매업(45~47) | 종합소매업 | 기타음·식료품위주종합소매업 | G47129 | Ua5Me2f5nN1Y7EXPRpKN9A== |
2 | 2020-10 | F | 50 | 14103***** | 경기도 | 2020-08 | 2015-03-14 | 일반과세자 | 2019 | 0 | 0 | 17072680 | 50000000 | 경기도자금 | 소상공인지원자금 | I숙박및음식점업(55~56) | 음식점업 | 한식일반음식점업 | I56111 | eVb1xm50VeNeCrV6NKnpYg== |
3 | 2020-10 | F | 40 | 22116***** | 경기도 | 2020-08 | 2015-06-10 | 일반과세자 | NaN | 0 | 0 | 0 | 100000000 | 경기도자금 | 소상공인지원자금 | C제조업(10~34) | 기타식품제조업 | 기타식품첨가물제조업 | C10749 | OKSoJ07f2GvslToPkIhoNw== |
4 | 2020-10 | M | 30 | 61142***** | 경기도 | 2020-08 | 2020-04-03 | 일반과세자 | 2019 | 0 | 0 | 0 | 50000000 | 경기도자금 | 소상공인지원자금 | H운수업(49~52) | 도로화물운송업 | 용달화물자동차운송업 | H49302 | k0Imt4oZHy4swytdpbk1Cw== |
df_seller.isnull().sum() # 이전과세년도에 빈값이 많음
기준년월 0 성별코드 0 연령대코드 0 사업자등록번호 0 시도명 0 신청년월 0 개업일자 0 과세유형명 0 이전과세년도 578 사업소득과세금액 0 근로소득과세금액 0 부가가치과세금액 0 신청금액 0 자금종류대분류명 0 자금종류중분류명 0 업종대분류명 0 업종중분류명 0 업종소분류명 0 업종코드 0 기업번호 0 dtype: int64
df_seller.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 778 entries, 0 to 777 Data columns (total 20 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 기준년월 778 non-null object 1 성별코드 778 non-null object 2 연령대코드 778 non-null int64 3 사업자등록번호 778 non-null object 4 시도명 778 non-null object 5 신청년월 778 non-null object 6 개업일자 778 non-null object 7 과세유형명 778 non-null object 8 이전과세년도 200 non-null float64 9 사업소득과세금액 778 non-null int64 10 근로소득과세금액 778 non-null int64 11 부가가치과세금액 778 non-null int64 12 신청금액 778 non-null int64 13 자금종류대분류명 778 non-null object 14 자금종류중분류명 778 non-null object 15 업종대분류명 778 non-null object 16 업종중분류명 778 non-null object 17 업종소분류명 778 non-null object 18 업종코드 778 non-null object 19 기업번호 778 non-null object dtypes: float64(1), int64(5), object(14) memory usage: 121.7+ KB
# 이번 분석에 사용하지 않을 컬럼 제거
drop_columns = ['시도명', '사업자등록번호', '이전과세년도', '개업일자', '자금종류대분류명', '자금종류중분류명', '업종코드', '기업번호']
df_seller = df_seller.drop(drop_columns, axis=1)
df_seller.head()
기준년월 | 성별코드 | 연령대코드 | 신청년월 | 과세유형명 | 사업소득과세금액 | 근로소득과세금액 | 부가가치과세금액 | 신청금액 | 업종대분류명 | 업종중분류명 | 업종소분류명 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 2020-10 | M | 50 | 2020-08 | 일반과세자 | 0 | 0 | 8058670 | 50000000 | C제조업(10~34) | 특수목적용기계제조업 | 주형및금형제조업 |
1 | 2020-10 | F | 30 | 2020-08 | 일반과세자 | 0 | 0 | 8491460 | 30000000 | G도매및소매업(45~47) | 종합소매업 | 기타음·식료품위주종합소매업 |
2 | 2020-10 | F | 50 | 2020-08 | 일반과세자 | 0 | 0 | 17072680 | 50000000 | I숙박및음식점업(55~56) | 음식점업 | 한식일반음식점업 |
3 | 2020-10 | F | 40 | 2020-08 | 일반과세자 | 0 | 0 | 0 | 100000000 | C제조업(10~34) | 기타식품제조업 | 기타식품첨가물제조업 |
4 | 2020-10 | M | 30 | 2020-08 | 일반과세자 | 0 | 0 | 0 | 50000000 | H운수업(49~52) | 도로화물운송업 | 용달화물자동차운송업 |
df_seller['업종대분류명'].unique()
# 뒤에 붙은 (10~34) 등은 불필요하므로 제거
array(['C제조업(10~34)', 'G도매및소매업(45~47)', 'I숙박및음식점업(55~56)', 'H운수업(49~52)', 'Q보건업및사회복지서비스업(86~87)', 'N사업시설관리및사업지원서비스업(74~76)', 'R예술;스포츠및여가관련서비스업(90~91)', 'P교육서비스업(85)', 'M전문;과학및기술서비스업(70~73)', 'F건설업(41~42)', 'S협회및단체;수리및기타개인서비스업(94~96)', 'L부동산업및임대업(68)', 'J정보통신업(58~63)'], dtype=object)
# https://stackoverflow.com/questions/44173155/pandas-use-apply-to-split-column-into-2
# https://kimginam1995.tistory.com/568
df_seller['업종대분류명'] = df_seller['업종대분류명'].apply(lambda x : x.split('(')[0])
df_seller['업종대분류명']
0 C제조업 1 G도매및소매업 2 I숙박및음식점업 3 C제조업 4 H운수업 ... 773 R예술;스포츠및여가관련서비스업 774 L부동산업및임대업 775 H운수업 776 G도매및소매업 777 G도매및소매업 Name: 업종대분류명, Length: 778, dtype: object
# https://programmers.co.kr/learn/courses/4008/lessons/48464
category_feature = [col for col in df_seller.columns if df_seller[col].dtypes == 'object']
for col in category_feature:
print(df_seller[col].unique())
print(df_seller[col].nunique())
['2020-10'] 1 ['M' 'F'] 2 ['2020-08' '2020-09' '2020-10' '2020-11' '2020-07'] 5 [' 일반과세자 ' ' 간이과세자 ' ' 부가가치세 면세사업자 '] 3 ['C제조업' 'G도매및소매업' 'I숙박및음식점업' 'H운수업' 'Q보건업및사회복지서비스업' 'N사업시설관리및사업지원서비스업' 'R예술;스포츠및여가관련서비스업' 'P교육서비스업' 'M전문;과학및기술서비스업' 'F건설업' 'S협회및단체;수리및기타개인서비스업' 'L부동산업및임대업' 'J정보통신업'] 13 ['특수목적용기계제조업' '종합소매업' '음식점업' '기타식품제조업' '도로화물운송업' '기타상품전문소매업' '의원' '가전제품및정보통신장비소매업' '주점및비알콜음료점업' '기타운송관련서비스업' '기타사업지원서비스업' '스포츠서비스업' '건축자재;철물및난방장치도매업' '일반교습학원' '나무제품제조업' '회계및세무관련서비스업' '무점포소매업' '실내건축및건축마무리공사업' '기타전문도매업' '상품중개업' '기타교육기관' '미용;욕탕및유사서비스업' '음·식료품및담배도매업' '전동기;발전기및전기변환·공급·제어장치제조업' '산업용농축산물및산동물도매업' '생활용품도매업' '직물직조및직물제품제조업' '전기및통신공사업' '건설장비운영업' '그외기타개인서비스업' '섬유;의복;신발및가죽제품소매업' '상품종합도매업' '기반조성및시설물축조관련전문공사업' '신발및신발부분품제조업' '부동산관련서비스업' '기계장비및관련물품도매업' '육상여객운송업' '고용알선및인력공급업' '그외기타제품제조업' '개인및가정용품임대업' '소프트웨어개발및공급업' '유원지및기타오락관련서비스업' '봉제의복제조업' '전구및조명장치제조업' '사진촬영및처리업' '개인및가정용품수리업' '기타비금속광물제품제조업' '음·식료품및담배소매업' '컴퓨터프로그래밍;시스템통합및관리업' '전문디자인업' '골판지;종이상자및종이용기제조업' '일반목적용기계제조업' '서적;잡지및기타인쇄물출판업' '자동차판매업' '구조용금속제품;탱크및증기발생기제조업' '연료소매업' '자동차부품및내장품판매업' '컴퓨터및통신장비수리업' '가구제조업' '광고업' '귀금속및장신용품제조업' '도서관;사적지및유사여가관련서비스업' '건축기술;엔지니어링및관련기술서비스업' '일반및생활숙박시설운영업' '반도체제조업' '컴퓨터및주변장치제조업' '플라스틱제품제조업' '영화;비디오물;방송프로그램제작및배급업' '인쇄및인쇄관련산업' '자동차신품부품제조업' '기타생활용품소매업' '텔레비전방송업' '기타금속가공제품제조업' '소화물전문운송업' '그외기타전문;과학및기술서비스업' '기타화학제품제조업' '전자부품제조업' '건물설비설치공사업' '1차철강제조업' '회사본부및경영컨설팅서비스업' '산업용기계및장비수리업' '토목건설업' '문화;오락및여가용품소매업' '자동차및모터사이클수리업' '기타종이및판지제품제조업' '기타정보서비스업' '인문및사회과학연구개발업'] 87 ['주형및금형제조업' '기타음·식료품위주종합소매업' '한식일반음식점업' '기타식품첨가물제조업' '용달화물자동차운송업' '애완용동물및관련용품소매업' '일반의원' '컴퓨터및주변장치;소프트웨어소매업' '슈퍼마켓' '커피전문점' '화물운송중개;대리및관련서비스업' '한식육류요리전문점' '그외기타분류안된사업지원서비스업' '일반화물자동차운송업' '한의원' '골프연습장운영업' '골재;벽돌및시멘트도매업' '통관대리및관련서비스업' '시계및귀금속소매업' '일반교과학원' '목재도구및주방용나무제품제조업' '세무사업' '전자상거래소매중개업' '도배;실내장식및내장목공사업' '인쇄및제책용기계제조업' '재생용재료수집및판매업' '산업용농축산물;섬유원료및동물중개업' '서양식음식점업' '외국어학원' '두발미용업' '그외기타스포츠시설운영업' '육류가공식품도매업' '전기회로접속장치제조업' '기타산업용농산물도매업' '화장품및화장용품도매업' '전자상거래소매업' '당구장운영업' '침구및관련제품제조업' '내부통신배선공사업' '통신기기소매업' '건설장비운영업' '애완동물장묘및보호서비스업' '개별화물자동차운송업' '속옷및잠옷소매업' '음악학원' '상품종합도매업' '수중공사업' '신발부분품제조업' '상품종합중개업' '부동산중개및대리업' '배전반및전기자동제어반제조업' '안경및렌즈소매업' '의복액세서리및모조장신구소매업' '체형등기타신체관리서비스업' '김밥및기타간이음식점업' '체인화편의점' '가전제품및부품도매업' '택시운송업' '고용알선업' '그외기타생활용품도매업' '간판및광고물제조업' '피자;햄버거;샌드위치및유사음식점업' '그외기타개인및가정용품임대업' '빵류;과자류;당류;초콜릿도매업' '응용소프트웨어개발및공급업' '노래연습장운영업' '기타미용업' '셔츠및블라우스제조업' '전시;컨벤션및행사대행업' '컴퓨터게임방운영업' '기타통신판매업' '일반용전기조명장치제조업' '치킨전문점' '인물사진및행사용영상촬영업' '기관구내식당업' '그외기타개인및가정용품수리업' '암면및유사제품제조업' '일식음식점업' '남자용겉옷소매업' '육류소매업' '컴퓨터시스템통합자문및구축서비스업' '비계및형틀공사업' '신발도매업' '제품디자인업' '커피가공업' '셔츠및블라우스소매업' '골판지제조업' '생활용가구도매업' '기타신선식품및단순가공식품도매업' '유압기기제조업' '문서작성업' '기타육상운송지원서비스업' '기타인쇄물출판업' '원목및건축관련목제품도매업' '태권도및무술교육기관' '중고자동차판매업' '기타직물제품제조업' '금속문;창;셔터및관련제품제조업' '운송장비용주유소운영업' '자동차신품타이어및튜브판매업' '전기용기계장비및관련기자재도매업' '통신장비수리업' '금속가구제조업' '탭;밸브및유사장치제조업' '광고대행업' '문구용품;회화용품;사무용품도매업' '그외기타분류안된교육기관' '기타산업용기계및장비도매업' '모조귀금속및모조장신용품제조업' '독서실운영업' '기타엔지니어링서비스업' '기타식료품소매업' '떡류제조업' '기타화학물질및화학제품도매업' '기타가공식품도매업' '피부미용업' '가방및기타가죽제품소매업' '여관업' '그외기타달리분류되지않은개인서비스업' '기타반도체소자제조업' '화장품;비누및방향제소매업' '컴퓨터제조업' '그외기타플라스틱제품제조업' '영화;비디오물및방송프로그램제작관련서비스업' '기타기술및직업훈련학원' '스크린인쇄업' '비알콜음료도매업' '기타주점업' '사무용가구및기기도매업' '의료용기구소매업' '경인쇄업' '기타자동차신품부품및내장품판매업' '일반서적출판업' '체력단련시설운영업' '컴퓨터학원' '사진처리업' '한식면요리전문점' '생맥주전문점' '그외자동차용신품부품제조업' '그외기타기계및장비도매업' '전기용품및조명장치소매업' '그외기타건축마무리공사업' '지상파방송업' '간이음식포장판매전문점' '컴퓨터및주변장치;소프트웨어도매업' '커피및차류도매업' '그외기타금속가공업' '택배업' '컴퓨터프로그래밍서비스업' '그외기타분류안된전문;과학및기술서비스업' '기타오락장운영업' '도장공사업' '가공및정제염제조업' '그외기타건축자재도매업' '여자용겉옷소매업' '가정용세탁업' '그외기타전자부품제조업' '치과의원' '화훼류및식물도매업' '배관및냉·난방공사업' '과실류도매업' '치약;비누및기타세제제조업' '도금;착색및기타표면처리강재제조업' '육류도매업' '경영컨설팅업' '미술학원' '자동차중고부품및내장품판매업' '기타물품취급장비제조업' '기타일반기계및장비수리업' '가구소매업' '유리및창호공사업' '의료용품도매업' '기타토목시설물건설업' '벽지및장판류도매업' '건강보조식품소매업' '기타예술학원' '신발소매업' '건물및토목엔지니어링서비스업' '레크리에이션교육기관' '시각디자인업' '운동및경기용품소매업' '남녀용겉옷및셔츠도매업' '건축설계및관련서비스업' '그외기타분류안된가정용품소매업' '교과서및학습서적출판업' '가죽및모피의복소매업' '서적임대업' '서적;잡지및기타인쇄물도매업' '방직용섬유및실도매업' '기타비알코올음료점업' '자동차전문수리업' '음반및비디오물도매업' '욕탕업' '그외기타상품전문도매업' '위생용종이제품제조업' '게임용구;인형및장난감소매업' '비누및세정제도매업' '광고매체판매업' '데이터베이스및온라인정보제공업' '기타인문및사회과학연구개발업' '생활용유리;요업;목재;금속제품및날붙이도매업'] 201
df_seller.describe()
연령대코드 | 사업소득과세금액 | 근로소득과세금액 | 부가가치과세금액 | 신청금액 | |
---|---|---|---|---|---|
count | 778 | 778 | 778 | 778 | 778 |
mean | 39 | 20450 | 19672 | 830922 | 56062982 |
std | 10 | 229220 | 216886 | 3114525 | 30448300 |
min | 20 | 0 | 0 | 0 | 10000000 |
25% | 30 | 0 | 0 | 0 | 30000000 |
50% | 40 | 0 | 0 | 0 | 50000000 |
75% | 40 | 0 | 0 | 0 | 100000000 |
max | 70 | 4380650 | 5139940 | 27417610 | 100000000 |
## 원본 데이터가 수정되어 문제 해결되었다!!
# 지수표기법(과학적 표기법): 1e+08은 10**8 = 1억
# 숫자형이 지수표기 식으로 되어 불편한 경우 판다스의 숫자형 표기 옵션을 바꿔준다
# https://zel0rd.tistory.com/33
# pd.options.display.float_format = '{:.0f}'.format
# df_seller.describe()
# pd.reset_option('display.float_format')
# https://pythonq.com/so/python/60301
# but 그래프에서도 지수 표현을 끌 경우 알아보기 어려워진다
numeric_feature = list(set(df_seller.columns) - set(category_feature))
numeric_feature = np.sort(numeric_feature)
for col in numeric_feature:
sns.distplot(df_seller.loc[df_seller[col].notnull(), col])
plt.title(col + ' 분포')
# ax = plt.gca()
# ax.get_xaxis().get_major_formatter().set_scientific(False)
plt.show()
# kde는 '추정치' 이므로 없는 값도 표시하여 오인지할수 있어 지운다
sns.distplot(df_seller['신청금액'], kde=False, bins=40)
plt.title('신청금액 분포 (상세)')
Text(0.5, 1.0, '신청금액 분포 (상세)')
sns.histplot(df_seller['신청금액'], bins=40) # 같은 기능
plt.title('신청금액 분포 (상세)')
Text(0.5, 1.0, '신청금액 분포 (상세)')
for col in category_feature:
plt.figure(figsize=(12,8))
df_seller[col].value_counts().sort_values().plot(kind='barh')
# plt.xticks(rotation = 45)
plt.title(col)
plt.show()
# df_seller[['업종중분류명', '신청금액']].groupby('업종중분류명').sum().sort_values(by=['신청금액'], ascending=False)[0:20].plot(kind='bar', cmap=plt.cm.Accent, figsize=(12,8)) #, title = "업종중분류별 신청액 상위 20 업종")
# plt.title('업종 중분류별 신청액 상위 20개 업종')
## 텍스트가 옆으로 누워 읽기 힘들다 (주석 없애고 그려보자)
# df_seller[['업종중분류명', '신청금액']].groupby('업종중분류명').sum().sort_values(by=['신청금액'], ascending=False)[0:20].plot(kind='barh', cmap=plt.cm.Accent, figsize=(12,8)) #, title = "업종중분류별 신청액 상위 20 업종")
# plt.title('업종 중분류별 신청액 상위 20개 업종')
## 제일 많은 것이 아래에 오는데 순서 바꾸고 싶다 (주석 없애고 그려보자)
df_seller_mid_20 = df_seller[['업종중분류명', '신청금액']].groupby('업종중분류명').sum().sort_values(by=['신청금액'])[-20:] # asending = True로 놓고 뒤에서부터 20개 가져오기
df_seller_mid_20.plot(kind='barh', color='tab:blue', figsize=(12,8))
plt.title('업종 중분류별 신청액 상위 20개 업종')
Text(0.5, 1.0, '업종 중분류별 신청액 상위 20개 업종')
# 코드 간단하게 (같은 기능)
df_seller_mid_20 = df_seller.groupby('업종중분류명')['신청금액'].sum().sort_values()[-20:]
df_seller_mid_20.plot(kind='barh', color='tab:blue', figsize=(12,8))
plt.title('업종 중분류별 신청액 상위 20개 업종')
Text(0.5, 1.0, '업종 중분류별 신청액 상위 20개 업종')
df_seller_low_20 = df_seller.groupby('업종소분류명')['신청금액'].sum().sort_values()[-20:]
df_seller_low_20.plot(kind='barh', color='tab:orange', figsize=(12,8))
plt.title('업종 소분류별 신청액 상위 20개 업종')
Text(0.5, 1.0, '업종 소분류별 신청액 상위 20개 업종')
df_seller.groupby(['연령대코드'])['신청금액'].sum().plot(kind='bar', color='tab:green', figsize=(8,6))
plt.xticks(rotation = 0)
plt.title("연령대별 신청금액 (총액)")
Text(0.5, 1.0, '연령대별 신청금액 (총액)')
df.groupby(['연령대코드'])['신청금액'].mean().plot(kind='bar', color='tab:red', figsize=(8,6))
plt.xticks(rotation = 0)
plt.title("연령대별 신청금액 (평균)")
Text(0.5, 1.0, '연령대별 신청금액 (평균)')
pd.reset_option('display.float_format') # 소숫점 없앤 옵션 취소 (필요하면 재설정)
df_seller.corr()
연령대코드 | 사업소득과세금액 | 근로소득과세금액 | 부가가치과세금액 | 신청금액 | |
---|---|---|---|---|---|
연령대코드 | 1.000000 | -0.024335 | -0.044772 | 0.024653 | 0.021672 |
사업소득과세금액 | -0.024335 | 1.000000 | 0.208257 | 0.462019 | 0.027707 |
근로소득과세금액 | -0.044772 | 0.208257 | 1.000000 | 0.171763 | 0.072882 |
부가가치과세금액 | 0.024653 | 0.462019 | 0.171763 | 1.000000 | 0.139136 |
신청금액 | 0.021672 | 0.027707 | 0.072882 | 0.139136 | 1.000000 |
plt.figure(figsize=(10,8))
sns.heatmap(df_seller.corr(),
annot = True,
cmap = 'RdYlBu_r',
linewidths=.5,
vmin = -1, vmax = 1,
)
# 소득세란 무엇인가?
# https://www.korea.kr
# 자영사업자는 부가가치세와 별도로 사업소득에 대한 소득세를 납부하여야 합니다
<AxesSubplot:>
# https://m.blog.naver.com/kiddwannabe/221763497317
mask = np.zeros_like(df_seller.corr(), dtype=np.bool)
mask[np.triu_indices_from(mask)] = True
plt.figure(figsize=(10,6))
sns.heatmap(df_seller.corr(),
annot = True,
mask = mask,
cmap = 'RdYlBu_r',
linewidths=.5,
cbar_kws={"shrink": .8},
vmin = -1, vmax = 1,
)
<AxesSubplot:>
folder_path = "./data/소상공인시장진흥공단_상가(상권)정보_20210630/"
all_files = glob.glob(folder_path + "/*.csv")
df_shop = pd.DataFrame() # "상가(상권)" : 데이터 넣을 데이터프레임 선언 (데이터마다 변수명 다르게)
li = []
for filename in all_files:
df = pd.read_csv(filename, index_col=None, header=0)
li.append(df)
df_shop = pd.concat(li, axis=0, ignore_index=True) # 데이터프레임에 데이터 할당 (변수명 일치하도록 주의)
df_shop.head()
상가업소번호 | 상호명 | 지점명 | 상권업종대분류코드 | 상권업종대분류명 | 상권업종중분류코드 | 상권업종중분류명 | 상권업종소분류코드 | 상권업종소분류명 | 표준산업분류코드 | ... | 건물관리번호 | 건물명 | 도로명주소 | 구우편번호 | 신우편번호 | 동정보 | 층정보 | 호정보 | 경도 | 위도 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 25033300 | 동그라미중고타이어 | NaN | D | 소매 | D23 | 자동차/자동차용품 | D23A04 | 타이어판매 | G45211 | ... | 4215011100110960006010791 | NaN | 강원도 강릉시 가작로 270 | 210110.0 | 25488.0 | 1 | NaN | NaN | 128.904472 | 37.770252 |
1 | 17174549 | 세인트존스호텔Ohcrab | NaN | O | 숙박 | O01 | 호텔/콘도 | O01A01 | 호텔/콘도 | NaN | ... | 4215011300100010001017124 | 세인트존스호텔 | 강원도 강릉시 창해로 307 | 210120.0 | 25467.0 | NaN | NaN | NaN | 128.920908 | 37.791299 |
2 | 17174079 | 평창라마다호텔 | NaN | O | 숙박 | O01 | 호텔/콘도 | O01A01 | 호텔/콘도 | NaN | ... | 4276038024102450036000001 | NaN | 강원도 평창군 대관령면 오목길 107 | 232954.0 | 25342.0 | NaN | NaN | NaN | 128.717971 | 37.660051 |
3 | 17173904 | 호텔탑스텐스카이라운지 | NaN | O | 숙박 | O01 | 호텔/콘도 | O01A01 | 호텔/콘도 | NaN | ... | 4215035029100920001000002 | NaN | 강원도 강릉시 옥계면 헌화로 455-34 | 210831.0 | 25633.0 | NaN | NaN | NaN | 129.052902 | 37.654680 |
4 | 20782013 | 행복나눔 | NaN | D | 소매 | D07 | 가정/주방/인테리어 | D07A05 | 정수기연수기 | G47320 | ... | 4211012000107980012030891 | NaN | 강원도 춘천시 후석로 275 | 200160.0 | 24282.0 | NaN | NaN | NaN | 127.752293 | 37.876199 |
5 rows × 39 columns
df_shop.columns
Index(['상가업소번호', '상호명', '지점명', '상권업종대분류코드', '상권업종대분류명', '상권업종중분류코드', '상권업종중분류명', '상권업종소분류코드', '상권업종소분류명', '표준산업분류코드', '표준산업분류명', '시도코드', '시도명', '시군구코드', '시군구명', '행정동코드', '행정동명', '법정동코드', '법정동명', '지번코드', '대지구분코드', '대지구분명', '지번본번지', '지번부번지', '지번주소', '도로명코드', '도로명', '건물본번지', '건물부번지', '건물관리번호', '건물명', '도로명주소', '구우편번호', '신우편번호', '동정보', '층정보', '호정보', '경도', '위도'], dtype='object')
# 사용할 변수만 선택 (번호, 코드, 관리번호, 우편번호 등 이번 분석에 의미 없는 컬럼 제외)
view_columns = ['상호명', '지점명', '상권업종대분류명', '상권업종중분류명',
'상권업종소분류명', '시도명', '시군구명',
'행정동명', '법정동명', '지번주소', '도로명주소', '경도', '위도']
df_shop_new = df_shop[view_columns]
df_shop_new.head()
상호명 | 지점명 | 상권업종대분류명 | 상권업종중분류명 | 상권업종소분류명 | 시도명 | 시군구명 | 행정동명 | 법정동명 | 지번주소 | 도로명주소 | 경도 | 위도 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 동그라미중고타이어 | NaN | 소매 | 자동차/자동차용품 | 타이어판매 | 강원도 | 강릉시 | 포남1동 | 포남동 | 강원도 강릉시 포남동 1096-6 | 강원도 강릉시 가작로 270 | 128.904472 | 37.770252 |
1 | 세인트존스호텔Ohcrab | NaN | 숙박 | 호텔/콘도 | 호텔/콘도 | 강원도 | 강릉시 | 초당동 | 강문동 | 강원도 강릉시 강문동 1-1 | 강원도 강릉시 창해로 307 | 128.920908 | 37.791299 |
2 | 평창라마다호텔 | NaN | 숙박 | 호텔/콘도 | 호텔/콘도 | 강원도 | 평창군 | 대관령면 | 대관령면 | 강원도 평창군 대관령면 횡계리 245-66 | 강원도 평창군 대관령면 오목길 107 | 128.717971 | 37.660051 |
3 | 호텔탑스텐스카이라운지 | NaN | 숙박 | 호텔/콘도 | 호텔/콘도 | 강원도 | 강릉시 | 옥계면 | 옥계면 | 강원도 강릉시 옥계면 금진리 92-1 | 강원도 강릉시 옥계면 헌화로 455-34 | 129.052902 | 37.654680 |
4 | 행복나눔 | NaN | 소매 | 가정/주방/인테리어 | 정수기연수기 | 강원도 | 춘천시 | 후평2동 | 후평동 | 강원도 춘천시 후평동 798-12 | 강원도 춘천시 후석로 275 | 127.752293 | 37.876199 |
df_shop_new.isnull().sum() # 지점명 결측치 많음
상호명 3 지점명 1895160 상권업종대분류명 0 상권업종중분류명 0 상권업종소분류명 0 시도명 0 시군구명 0 행정동명 11659 법정동명 1974 지번주소 0 도로명주소 12 경도 0 위도 0 dtype: int64
msno.matrix(df_shop_new)
<AxesSubplot:>
# 경도, 위도 정보로 지도 그려보기
df_shop_new[:10000].plot.scatter(x='경도', y='위도', grid=True)
<AxesSubplot:xlabel='경도', ylabel='위도'>
df_shop_new['시도명'].unique()
array(['강원도', '경기도', '경상남도', '경상북도', '광주광역시', '대구광역시', '대전광역시', '부산광역시', '서울특별시', '세종특별자치시', '울산광역시', '인천광역시', '전라남도', '전라북도', '제주특별자치도', '충청남도', '충청북도'], dtype=object)
# 전국 상권정보가 다 있다(이전엔 서울, 부산만 있었음) -> 이 중 서울과 경기만 선택
# https://ddolcat.tistory.com/845
# df_shop_seoul = df_shop_new.loc[df_shop_new['도로명주소'].str.startswith('서울', na=False)]
# df_shop_kyung = df_shop_new.loc[df_shop_new['도로명주소'].str.startswith('경기', na=False)]
# df_shop_kyung['시도'] = df_shop_kyung['도로명주소'].str.split(' ', expand=True)[0]
# df_shop_kyung['시군구'] = df_shop_kyung['도로명주소'].str.split(' ', expand=True)[1]
# 서울/서울특별시/서울시, 경기/경기도 등으로 입력된 경우
# '도로명주소'를 전처리해 정확한 시도/시군구명을 추출하는 법
# 이 데이터에서는 '시도명'이 unique하므로 아래의 간단한 방법을 사용한다
df_shop_seoul = df_shop_new.loc[df_shop_new['시도명'] == '서울특별시']
df_shop_kyung = df_shop_new.loc[df_shop_new['시도명'] == '경기도']
print(df_shop_seoul.shape)
print(df_shop_kyung.shape)
(316078, 13) (505809, 13)
df_shop_seoul.plot.scatter(x='경도', y='위도', color='tab:blue', figsize=(16, 12), grid=True)
<AxesSubplot:xlabel='경도', ylabel='위도'>
df_shop_kyung.plot.scatter(x='경도', y='위도', color='tab:green', figsize=(16, 12), grid=True)
<AxesSubplot:xlabel='경도', ylabel='위도'>
print(df_shop_seoul['시도명'].unique())
print(df_shop_seoul['시군구명'].unique())
print(df_shop_seoul['시군구명'].nunique())
['서울특별시'] ['서초구' '동작구' '종로구' '영등포구' '송파구' '성동구' '성북구' '마포구' '강동구' '관악구' '양천구' '강남구' '중랑구' '은평구' '서대문구' '중구' '동대문구' '강북구' '광진구' '용산구' '강서구' '구로구' '도봉구' '노원구' '금천구'] 25
print(df_shop_kyung['시도명'].unique())
print(df_shop_kyung['시군구명'].unique()) # 수원시 / 수원시 팔달구, 수원시 영동구, 수원시 권선구, 수원시 장안구 등 처리 필요 (여기에선 진행하지 않음)
print(df_shop_kyung['시군구명'].nunique())
['경기도'] ['파주시' '평택시' '광명시' '성남시 분당구' '김포시' '의정부시' '광주시' '수원시 팔달구' '화성시' '수원시 영통구' '시흥시' '수원시 권선구' '군포시' '안산시 상록구' '포천시' '용인시 처인구' '안양시 동안구' '안양시 만안구' '고양시 덕양구' '고양시 일산동구' '안산시 단원구' '하남시' '수원시 장안구' '동두천시' '구리시' '용인시' '성남시 수정구' '가평군' '양주시' '의왕시' '부천시' '남양주시' '양평군' '용인시 수지구' '이천시' '고양시 일산서구' '안성시' '용인시 기흥구' '성남시 중원구' '오산시' '연천군' '여주시' '과천시' '안산시' '고양시' '수원시'] 46
# 전체 데이터를 그리면 시간이 오래 걸리기 때문에
# 슬라이싱으로 [:10000] 10000 개 포인트만 그린다
plt.figure(figsize=(16, 12))
sns.scatterplot(data=df_shop_seoul[:10000], x='경도', y='위도', hue='시군구명')
plt.title('서울시 구별 상권 분포')
Text(0.5, 1.0, '서울시 구별 상권 분포')
plt.figure(figsize=(16, 12))
sns.scatterplot(data=df_shop_kyung[:20000], x='경도', y='위도', hue='시군구명')
plt.title('경기도 시군구별 상권 분포')
Text(0.5, 1.0, '경기도 시군구별 상권 분포')
df_shop_seoul['상권업종대분류명'].value_counts()
음식 126203 소매 89857 생활서비스 55634 학문/교육 21426 부동산 12748 관광/여가/오락 6633 숙박 2322 스포츠 1255 Name: 상권업종대분류명, dtype: int64
count_status = pd.value_counts(df_shop_seoul['상권업종대분류명'].values)
count_status.sort_values().plot.barh(grid=True, figsize=(15,8), fontsize=13)
plt.title('서울시 상권업종 대분류 순위', fontsize=14)
Text(0.5, 1.0, '서울시 상권업종 대분류 순위')
plt.figure(figsize=(16, 12))
sns.scatterplot(data=df_shop_seoul[:10000], x='경도', y='위도', hue='상권업종대분류명')
plt.title('서울시 상권업종 대분류 분포', fontsize=14)
Text(0.5, 1.0, '서울시 상권업종 대분류 분포')
df_shop_seoul
상호명 | 지점명 | 상권업종대분류명 | 상권업종중분류명 | 상권업종소분류명 | 시도명 | 시군구명 | 행정동명 | 법정동명 | 지번주소 | 도로명주소 | 경도 | 위도 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1284600 | 비지트 | NaN | 음식 | 한식 | 한식/백반/한정식 | 서울특별시 | 서초구 | 방배4동 | 방배동 | 서울특별시 서초구 방배동 854-18 | 서울특별시 서초구 동광로18길 82 | 126.991394 | 37.488375 |
1284601 | 쓰리에프 | NaN | 음식 | 한식 | 한식/백반/한정식 | 서울특별시 | 동작구 | 사당2동 | 사당동 | 서울특별시 동작구 사당동 139-72 | 서울특별시 동작구 동작대로27가길 12 | 126.980952 | 37.487105 |
1284602 | 채움 | NaN | 음식 | 한식 | 한식/백반/한정식 | 서울특별시 | 종로구 | 종로1.2.3.4가동 | 수송동 | 서울특별시 종로구 수송동 58 | 서울특별시 종로구 삼봉로 81 | 126.981794 | 37.572387 |
1284603 | 호구의주방 | NaN | 소매 | 가정/주방/인테리어 | 주방가구판매 | 서울특별시 | 영등포구 | 양평2동 | 양평동4가 | 서울특별시 영등포구 양평동4가 160-2 | 서울특별시 영등포구 선유로 269 | 126.897892 | 37.536700 |
1284604 | 다향 | NaN | 음식 | 한식 | 한식/백반/한정식 | 서울특별시 | 서초구 | 서초3동 | 서초동 | 서울특별시 서초구 서초동 1485-3 | 서울특별시 서초구 효령로 230 | 127.009382 | 37.483436 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
1600673 | 김씨네주방 | NaN | 음식 | 한식 | 한식/백반/한정식 | 서울특별시 | 서대문구 | 홍은2동 | 홍은동 | 서울특별시 서대문구 홍은동 456 | 서울특별시 서대문구 모래내로 309 | 126.931473 | 37.578889 |
1600674 | 핫플레이스 | NaN | 음식 | 한식 | 한식/백반/한정식 | 서울특별시 | 마포구 | 연남동 | 연남동 | 서울특별시 마포구 연남동 515-24 | 서울특별시 마포구 연남로 29 | 126.921671 | 37.562230 |
1600675 | 경인철형사 | NaN | 소매 | 철물/난방/건설자재소매 | 철물/건설자재소매 | 서울특별시 | 강동구 | 성내3동 | 성내동 | 서울특별시 강동구 성내동 420-46 | 서울특별시 강동구 성안로 70 | 127.131765 | 37.529776 |
1600676 | 솔시카고피자 | NaN | 음식 | 패스트푸드 | 피자전문 | 서울특별시 | 동작구 | 신대방1동 | 신대방동 | 서울특별시 동작구 신대방동 719 | 서울특별시 동작구 신대방1가길 38 | 126.906921 | 37.487893 |
1600677 | 피자버거플러스 | NaN | 음식 | 패스트푸드 | 피자전문 | 서울특별시 | 용산구 | 보광동 | 보광동 | 서울특별시 용산구 보광동 81-2 | 서울특별시 용산구 보광로 15 | 127.000969 | 37.525913 |
316078 rows × 13 columns
df_shop_seoul[df_shop_seoul['상권업종대분류명'] == '음식'].groupby(['시군구명']).count().sort_values()
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-126-2f98bcc5f523> in <module> ----> 1 df_shop_seoul[df_shop_seoul['상권업종대분류명'] == '음식'].groupby(['시군구명']).count().sort_values() ~\anaconda\lib\site-packages\pandas\util\_decorators.py in wrapper(*args, **kwargs) 309 stacklevel=stacklevel, 310 ) --> 311 return func(*args, **kwargs) 312 313 return wrapper TypeError: sort_values() missing 1 required positional argument: 'by'
df_shop_seoul_food = df_shop_seoul[df_shop_seoul['상권업종대분류명'] == '음식']
df_food_seoul = pd.DataFrame(df_shop_seoul_food['시군구명'].value_counts().reset_index())
df_food_seoul.columns = ['시군구명', '음식점수']
df_food_seoul
df_food_seoul.to_csv('./data/df_food_seoul.csv', index=False)
df_shop_seoul.to_csv('./data/df_shop_seoul.csv', index=False)
df_shop_kyung['상권업종대분류명'].value_counts()
음식 183836 소매 158674 생활서비스 83434 학문/교육 39236 부동산 21576 관광/여가/오락 11133 숙박 5503 스포츠 2417 Name: 상권업종대분류명, dtype: int64
count_status = pd.value_counts(df_shop_kyung['상권업종대분류명'].values)
count_status.sort_values().plot.barh(grid=True, figsize=(15,8), color='tab:green', fontsize=13)
plt.title('경기도 상권업종 대분류 순위', fontsize=14)
Text(0.5, 1.0, '경기도 상권업종 대분류 순위')
plt.figure(figsize=(16, 12))
sns.scatterplot(data=df_shop_kyung[:10000], x='경도', y='위도', hue='상권업종대분류명')
plt.title('경기도 상권업종 대분류 분포', fontsize=14)
Text(0.5, 1.0, '경기도 상권업종 대분류 분포')
df_shop_seoul_food = df_shop_seoul[df_shop_seoul['상권업종대분류명'] == '음식']
df_shop_seoul_food['상권업종중분류명'].value_counts()
한식 43770 커피점/카페 20832 유흥주점 13131 분식 11069 일식/수산물 8179 양식 7087 닭/오리요리 5594 제과제빵떡케익 5104 패스트푸드 4798 중식 3468 별식/퓨전요리 2269 부페 467 기타음식업 356 음식배달서비스 79 Name: 상권업종중분류명, dtype: int64
count_status = pd.value_counts(df_shop_seoul_food['상권업종중분류명'].values)
count_status.sort_values().plot.barh(grid=True, figsize=(15,8), fontsize=13)
plt.title('서울시 <음식> 상권 중분류 순위', fontsize=14)
Text(0.5, 1.0, '서울시 <음식> 상권 중분류 순위')
plt.figure(figsize=(16, 12))
sns.scatterplot(data=df_shop_seoul_food[:10000], x='경도', y='위도', hue='상권업종중분류명')
plt.title('서울시 <음식> 상권 중분류 분포', fontsize=14)
Text(0.5, 1.0, '서울시 <음식> 상권 중분류 분포')
df_shop_kyung_food = df_shop_kyung[df_shop_kyung['상권업종대분류명'] == '음식']
df_shop_kyung_food['시군구명'].value_counts()
화성시 10766 남양주시 8671 파주시 8666 평택시 8665 김포시 7281 시흥시 7010 부천시 6594 고양시 덕양구 5959 성남시 분당구 5942 의정부시 5489 광주시 5303 고양시 일산동구 5264 이천시 5017 포천시 4591 용인시 처인구 4567 양주시 4456 안성시 4397 용인시 기흥구 4334 안산시 단원구 4192 안양시 동안구 4151 수원시 영통구 4022 수원시 권선구 3803 수원시 팔달구 3750 하남시 3700 오산시 3451 안산시 상록구 3387 고양시 일산서구 3376 성남시 수정구 3149 안양시 만안구 3030 용인시 수지구 3028 성남시 중원구 2844 수원시 장안구 2831 광명시 2816 군포시 2790 양평군 2762 여주시 2743 구리시 2575 가평군 2068 동두천시 1882 의왕시 1751 연천군 1172 안산시 769 과천시 617 용인시 153 수원시 29 고양시 23 Name: 시군구명, dtype: int64
count_status = pd.value_counts(df_shop_kyung_food['시군구명'].values)
count_status.sort_values().plot.barh(grid=True, figsize=(15,10), color='tab:green', fontsize=10)
plt.title('경기도 <음식> 상권 중분류 시군구별 순위', fontsize=14)
Text(0.5, 1.0, '경기도 <음식> 상권 중분류 시군구별 순위')
plt.figure(figsize=(16, 12))
sns.scatterplot(data=df_shop_kyung_food[:10000], x='경도', y='위도', hue='시군구명', alpha='auto')
plt.title('경기도 <음식> 상권 중분류 분포', fontsize=14)
Text(0.5, 1.0, '경기도 <음식> 상권 중분류 분포')
df_shop_seoul_food_kor = df_shop_seoul[df_shop_seoul['상권업종중분류명'] == '한식']
df_shop_seoul_food_kor['시군구명'].value_counts()
강남구 4135 마포구 3095 송파구 2851 서초구 2182 강서구 2135 영등포구 2133 종로구 1781 강동구 1772 은평구 1728 관악구 1705 중구 1640 동대문구 1632 성북구 1542 구로구 1520 용산구 1510 성동구 1493 강북구 1402 광진구 1399 중랑구 1346 서대문구 1324 노원구 1265 금천구 1126 양천구 1112 동작구 1031 도봉구 911 Name: 시군구명, dtype: int64
count_status = pd.value_counts(df_shop_seoul_food_kor['시군구명'].values)
count_status.sort_values().plot.barh(grid=True, figsize=(15,10), fontsize=10)
plt.title('서울시 <한식> 상권 구별 순위', fontsize=14)
Text(0.5, 1.0, '서울시 <한식> 상권 구별 순위')
plt.figure(figsize=(16, 12))
sns.scatterplot(data=df_shop_seoul_food_kor[:10000], x='경도', y='위도', hue='시군구명', alpha='auto')
plt.title('서울시 <한식> 상권 구별 분포', fontsize=14)
Text(0.5, 1.0, '서울시 <한식> 상권 구별 분포')
df_shop_kyung_food_kor = df_shop_kyung[df_shop_kyung['상권업종중분류명'] == '한식']
df_shop_kyung_food_kor['시군구명'].value_counts()
화성시 4180 파주시 3669 남양주시 3518 평택시 3482 시흥시 2871 김포시 2763 고양시 덕양구 2278 포천시 2262 광주시 2199 양주시 2083 의정부시 2027 안성시 1997 이천시 1953 부천시 1928 용인시 처인구 1899 고양시 일산동구 1893 성남시 분당구 1865 수원시 권선구 1505 용인시 기흥구 1487 안산시 단원구 1487 수원시 영통구 1479 하남시 1460 수원시 팔달구 1434 오산시 1329 양평군 1296 안양시 동안구 1284 여주시 1277 안산시 상록구 1230 수원시 장안구 1106 성남시 수정구 1079 고양시 일산서구 1075 광명시 1031 용인시 수지구 1012 성남시 중원구 1012 안양시 만안구 972 가평군 937 군포시 918 구리시 904 동두천시 802 의왕시 653 연천군 495 안산시 258 과천시 225 용인시 50 수원시 10 고양시 8 Name: 시군구명, dtype: int64
df_shop_kyung_food_kor['시군구명'].values
array(['파주시', '파주시', '파주시', ..., '안양시 만안구', '평택시', '평택시'], dtype=object)
count_status = pd.value_counts(df_shop_kyung_food_kor['시군구명'].values)
count_status.sort_values().plot.barh(grid=True, figsize=(15,10), fontsize=10, color='tab:green')
plt.title('경기도 <한식> 상권 시군구별 순위', fontsize=14)
Text(0.5, 1.0, '경기도 <한식> 상권 시군구별 순위')
plt.figure(figsize=(16, 12))
sns.scatterplot(data=df_shop_kyung_food_kor[:10000], x='경도', y='위도', hue='시군구명', alpha='auto')
plt.title('경기도 <한식> 상권 구별 분포', fontsize=14)
Text(0.5, 1.0, '경기도 <한식> 상권 구별 분포')
import folium
lat = df_shop_seoul_food_kor['위도'].mean()
long = df_shop_seoul_food_kor['경도'].mean()
lat, long
(37.54595494678215, 126.99287479041476)
m = folium.Map([lat, long])
m
for i in df_shop_seoul_food_kor.index[:10]:
print(i)
1284600 1284601 1284602 1284604 1284611 1284612 1284613 1284614 1284615 1284616
for i in df_shop_seoul_food_kor.index[:10]:
sub_lat = df_shop_seoul_food_kor.loc[i, '위도']
sub_long = df_shop_seoul_food_kor.loc[i, '경도']
print(i, sub_lat, sub_long)
1284600 37.4883745422712 126.991394095675 1284601 37.4871045502058 126.980951647638 1284602 37.5723869222964 126.981794436761 1284604 37.4834357780284 127.009382169497 1284611 37.5561971380176 127.159471263976 1284612 37.562176119867 126.924659774897 1284613 37.5506889789685 126.919845300945 1284614 37.4711902396253 126.9377898093 1284615 37.512376125437 127.112318758601 1284616 37.5513400257924 126.956164271993
df_shop_seoul_food_kor.columns
Index(['상호명', '지점명', '상권업종대분류명', '상권업종중분류명', '상권업종소분류명', '시도명', '시군구명', '행정동명', '법정동명', '지번주소', '도로명주소', '경도', '위도'], dtype='object')
m = folium.Map([lat, long])
for i in df_shop_seoul_food_kor.index[:10]:
sub_lat = df_shop_seoul_food_kor.loc[i, '위도']
sub_long = df_shop_seoul_food_kor.loc[i, '경도']
title =f"{df_shop_seoul_food_kor.loc[i, '상호명']} - {df_shop_seoul_food_kor.loc[i, '도로명주소']}"
# print(i, sub_lat, sub_long, title)
folium.Marker([sub_lat, sub_long], popup=title).add_to(m)
m
m = folium.Map([lat, long])
for i in df_shop_seoul_food_kor.index[:10]:
sub_lat = df_shop_seoul_food_kor.loc[i, '위도']
sub_long = df_shop_seoul_food_kor.loc[i, '경도']
title =f"{df_shop_seoul_food_kor.loc[i, '상호명']} - {df_shop_seoul_food_kor.loc[i, '도로명주소']}"
# print(i, sub_lat, sub_long, title)
folium.CircleMarker([sub_lat, sub_long], popup=title).add_to(m)
m
m = folium.Map([lat, long], zoom_start=11, tiles='Stamen Toner')
for i in df_shop_seoul_food_kor.index[:1000]:
sub_lat = df_shop_seoul_food_kor.loc[i, '위도']
sub_long = df_shop_seoul_food_kor.loc[i, '경도']
title =f"{df_shop_seoul_food_kor.loc[i, '상호명']} - {df_shop_seoul_food_kor.loc[i, '도로명주소']}"
# print(i, sub_lat, sub_long, title)
folium.CircleMarker([sub_lat, sub_long], radius=3, popup=title).add_to(m)
m
df_shop_seoul_food_kor.groupby('시군구명')['상호명'].count()
시군구명 강남구 4135 강동구 1772 강북구 1402 강서구 2135 관악구 1705 광진구 1399 구로구 1520 금천구 1126 노원구 1265 도봉구 911 동대문구 1632 동작구 1031 마포구 3095 서대문구 1324 서초구 2182 성동구 1493 성북구 1542 송파구 2851 양천구 1112 영등포구 2133 용산구 1510 은평구 1728 종로구 1781 중구 1639 중랑구 1346 Name: 상호명, dtype: int64
pd.DataFrame(df_shop_seoul_food_kor.groupby('시군구명')['상호명'].count())
상호명 | |
---|---|
시군구명 | |
강남구 | 4135 |
강동구 | 1772 |
강북구 | 1402 |
강서구 | 2135 |
관악구 | 1705 |
광진구 | 1399 |
구로구 | 1520 |
금천구 | 1126 |
노원구 | 1265 |
도봉구 | 911 |
동대문구 | 1632 |
동작구 | 1031 |
마포구 | 3095 |
서대문구 | 1324 |
서초구 | 2182 |
성동구 | 1493 |
성북구 | 1542 |
송파구 | 2851 |
양천구 | 1112 |
영등포구 | 2133 |
용산구 | 1510 |
은평구 | 1728 |
종로구 | 1781 |
중구 | 1639 |
중랑구 | 1346 |
pd.DataFrame(df_shop_seoul_food_kor.groupby('시군구명')['상호명'].count()).reset_index()
시군구명 | 상호명 | |
---|---|---|
0 | 강남구 | 4135 |
1 | 강동구 | 1772 |
2 | 강북구 | 1402 |
3 | 강서구 | 2135 |
4 | 관악구 | 1705 |
5 | 광진구 | 1399 |
6 | 구로구 | 1520 |
7 | 금천구 | 1126 |
8 | 노원구 | 1265 |
9 | 도봉구 | 911 |
10 | 동대문구 | 1632 |
11 | 동작구 | 1031 |
12 | 마포구 | 3095 |
13 | 서대문구 | 1324 |
14 | 서초구 | 2182 |
15 | 성동구 | 1493 |
16 | 성북구 | 1542 |
17 | 송파구 | 2851 |
18 | 양천구 | 1112 |
19 | 영등포구 | 2133 |
20 | 용산구 | 1510 |
21 | 은평구 | 1728 |
22 | 종로구 | 1781 |
23 | 중구 | 1639 |
24 | 중랑구 | 1346 |
df_seoul_kor = pd.DataFrame(df_shop_seoul_food_kor.groupby('시군구명')['상호명'].count()).reset_index()
df_seoul_kor.columns = ['구', '한식 매장수']
df_seoul_kor
구 | 한식 매장수 | |
---|---|---|
0 | 강남구 | 4135 |
1 | 강동구 | 1772 |
2 | 강북구 | 1402 |
3 | 강서구 | 2135 |
4 | 관악구 | 1705 |
5 | 광진구 | 1399 |
6 | 구로구 | 1520 |
7 | 금천구 | 1126 |
8 | 노원구 | 1265 |
9 | 도봉구 | 911 |
10 | 동대문구 | 1632 |
11 | 동작구 | 1031 |
12 | 마포구 | 3095 |
13 | 서대문구 | 1324 |
14 | 서초구 | 2182 |
15 | 성동구 | 1493 |
16 | 성북구 | 1542 |
17 | 송파구 | 2851 |
18 | 양천구 | 1112 |
19 | 영등포구 | 2133 |
20 | 용산구 | 1510 |
21 | 은평구 | 1728 |
22 | 종로구 | 1781 |
23 | 중구 | 1639 |
24 | 중랑구 | 1346 |
df_kor_gu = pd.DataFrame(df_shop_seoul_food_kor.groupby('시군구명')['상호명'].count())
df_kor_gu.head()
상호명 | |
---|---|
시군구명 | |
강남구 | 4135 |
강동구 | 1772 |
강북구 | 1402 |
강서구 | 2135 |
관악구 | 1705 |
import json
# geo_path = 'data/seoul_municipalities_geo_simple.json'
geo_path = './data/skorea_municipalities_geo_simple.json'
geo_json = json.load(open(geo_path, encoding='utf-8'))
# https://python-visualization.github.io/folium/quickstart.html
# https://matplotlib.org/stable/gallery/color/colormap_reference.html
map = folium.Map(location=[df_shop_seoul['위도'].mean(), df_shop_seoul['경도'].mean()],
zoom_start=11)
map.choropleth(geo_data = geo_json,
data = df_kor_gu['상호명'],
columns = [df_seoul_kor.index, df_kor_gu['상호명']],
fill_color = 'OrRd',
key_on = 'feature.properties.name',
fill_opacity=0.7,
line_opacity=0.2,
highlight=True)
map